#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

static const int V = 100;
int parent[V];

struct Edge
{
	int src, des, cost;
	bool operator<(const Edge& rhs) const
	{
		return cost < rhs.cost;
	}
};
vector<Edge> edges;

void init(int n)
{
	edges.clear();
	for (int i = 0; i < n; ++i)
		parent[i] = -1;
}

int root(int& v)
{
	int depth = 0;
	while (parent[v] != -1)
	{
		v = parent[v];
		++depth;
	}
	return depth;
}

bool merge(int& a, int& b)
{
	int d1 = root(a);
	int d2 = root(b);
	if (a == b)
		return false;

	if (d1 < d2)
		parent[a] = b;
	else
		parent[b] = a;

	return true;
}

int Kruskal(int n)
{
	sort(edges.begin(), edges.end());
	int amount = 0;
	for (vector<Edge>::iterator it = edges.begin(); it != edges.end(); ++it)
	{
		if (merge(it->src, it->des))
		{
			amount += it->cost;
			if (--n == 1)
				return amount;
		}
	}
	return amount;
}

int main()
{
	while (1)
	{
		int n;
		scanf ("%d", &n);
		if (n == 0)
			break;

		init (n);

		int need = n;
		int c = n * (n - 1) / 2;
		while (c--)
		{
			Edge e;
			int s;
			scanf ("%d%d%d%d", &e.src, &e.des, &e.cost, &s);
			--e.src, --e.des;
			if (s == 0)
			{
				edges.push_back(e);
			}
			else
			{
				if (merge(e.src, e.des))
					--need;
			}
		}
		int amount = Kruskal(need);
		printf ("%d\n", amount);
	}
	return 0;
}